Skip to content

Do not report a move that succeeded as failed - #840

Merged
SimonCropp merged 2 commits into
mainfrom
fix-move-directory-guard
Aug 23, 2026
Merged

Do not report a move that succeeded as failed#840
SimonCropp merged 2 commits into
mainfrom
fix-move-directory-guard

Conversation

@SimonCropp

Copy link
Copy Markdown
Member

Accepting a tracked move removes the directory the received file sat in when
nothing is left in it, which is tidying up after a move that has already happened.
Only IOException was caught there, so a directory whose parent will not have it
removed threw UnauthorizedAccessException out of the accept - EACCES from rmdir,
which .NET reports as that rather than as an IO error.

The caller reads a throw as the move having failed, so the entry went back on the
queue with an error on it, and the retry then failed with file not found: the temp
file had been moved by the attempt that "failed". The enumerate is inside the guard
too now, since it can refuse for the same reason.

The test for it is Unix only. A read-only directory on Windows raises IOException,
which was always caught, so the case cannot be reached there.

Accepting a tracked move removes the directory the received file sat in when
nothing is left in it, which is tidying up after a move that has already happened.
Only IOException was caught there, so a directory whose parent will not have it
removed threw UnauthorizedAccessException out of the accept - EACCES from rmdir,
which .NET reports as that rather than as an IO error.

The caller reads a throw as the move having failed, so the entry went back on the
queue with an error on it, and the retry then failed with file not found: the temp
file had been moved by the attempt that "failed". The enumerate is inside the guard
too now, since it can refuse for the same reason.

The test for it is Unix only. A read-only directory on Windows raises IOException,
which was always caught, so the case cannot be reached there.
The test made the whole temp directory read only, so the move could not write its
target either and failed for the reason the test was meant to rule out. The received
file is two deep now and only the directory holding it is locked, so everything the
move itself does stays permitted and the only thing denied is the removal after it.

TUnit's own RunOn does the platform restriction, which the rest of the suite already
uses.
@SimonCropp
SimonCropp merged commit f858812 into main Aug 23, 2026
8 checks passed
@SimonCropp
SimonCropp deleted the fix-move-directory-guard branch August 23, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant